package org.tri.gui.view;

import furbelow.SpinningDial;
import furbelow.WaitIndicator;
import java.awt.Font;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
import java.util.concurrent.ExecutionException;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.text.DefaultFormatterFactory;
import org.tri.entity.Establecimiento;
import org.tri.entity.Productor;
import org.tri.gui.MainFrame;
import org.tri.gui.worker.*;
import org.tri.gui.worker.exceptions.EstablecimientoDuplicadoException;
import org.tri.gui.worker.retrievers.BusquedaDataRetriever;
import org.tri.model.EntityComboBoxModel;
import org.tri.persistence.search.BusquedaProductor;
import org.tri.swing.AbstractEditableLabel;
import org.tri.swing.SwingUtils;

/**
 * El dialog {@code EstablecimientoDialog} es una vista que permite ver, 
 * modificar, agregar y eliminar establecimientos.
 * @author kiira.
 * @version 1.0, Feb 11, 2012
 */
public class EstablecimientoView extends javax.swing.JDialog implements
        PropertyChangeListener, ComboFillListener {

    /** Combo model utilizado en el EditableLableCB. */
    private EntityComboBoxModel<Productor> productorComboModel;
    /** Indice por defecto del modelo de productores. */
    private int defaultIndexProductor;
    /** Establecimiento que esta vista representa. */
    private Establecimiento establecimiento;
    /** Bandera que indica si el establecimiento es nuevo o no. */
    private boolean establecimientoNuevo;
    /** Valor que indica el resultado de la operación con la vista. */
    private int result;
    /** Bandera que indica si la vista 
     * se abrió para eliminar el establecimiento. */
    private boolean toDelete;
    /** Icono de espera. */
    private SpinningDial loadingIcon;
    /** Componente para bloquear acciones mientras se esta realizando una tarea. */
    private WaitIndicator waitIndicator;
    
    /**
     * Crea una nueva vista utilizando el establecimiento indicado como backend
     * para los datos representados.
     * @param parent frame padre del dialog.
     * @param modal bandera que indica si la vista es modal.
     * @param establecimiento establecimiento a utilizar en la vista.
     */
    public EstablecimientoView( java.awt.Frame parent, boolean modal, 
                                Establecimiento establecimiento ) {
        super(parent, modal);
               
        //creamos el modelo de productores
        productorComboModel = new EntityComboBoxModel<Productor>(
        Productor.class, "razonSocial" );
                
        initComponents();
        
        //alineamos el componente
        setLocationRelativeTo( parent );
               
        //asignamos el establecimiento
        setEstablecimiento( establecimiento );
        
        //agregamos el listener de modificación a los campos obligatorios
        //para activar/desactivar el botón de guardar acorde a la situación
        eLTFNombreEstablecimiento.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLFTFRenspa.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLCBProductor.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLFTFCuig.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLFTFCV.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLTFDireccionPostal.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLTFPartido.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLTFProvincia.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLTFLote.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLFTFUltimaCaravana.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        eLFTFSuperficie.addPropertyChangeListener( 
                AbstractEditableLabel.MODIFIED_PROPERTY, this );
        
        //inicializamos el icono de loading
        loadingIcon = new SpinningDial( 20, 20, 10 );
        
        //cargamos asincronamente los productores en el combo box
        //en un thread separado cargamos los productores
        ComboFillWorker<Productor> worker = new ComboFillWorker<Productor>(
                productorComboModel,
                new BusquedaDataRetriever<Productor>(
                new BusquedaProductor() ) );

        worker.addComboFillListener( this );

        //ejectumos el worker
        worker.execute();
        
    }//end constructor
    
    /**
     * Este constructor alternativo se utiliza cuando se desea crear un nuevo
     * establecimiento, pero utilizando un productor como productor default
     * inicial para el mismo.
     * @param parent frame padre de este dialog.
     * @param modal bandera que indica si la vista es modal.
     * @param productor productor que se desea asignar como modal.
     */
    public EstablecimientoView( java.awt.Frame parent, boolean modal, 
                                                   final Productor productor ) {
        this( parent, modal, (Establecimiento)null );
               
        //agregamos un listener al modelo de productor para que el productor
        //designado sea seleccionado una vez que se complete la carga de
        //productores
        productorComboModel.addListDataListener(
                new ListDataListener() {

                    /**
                     * {@inheritDoc}
                     */
                    @Override
                    public void intervalAdded( ListDataEvent e ) {
                        //asignamos el productor
                        eLCBProductor.setDefaultValue( 
                                productor.getRazonSocial() );
                        defaultIndexProductor = eLCBProductor.getSelectedIndex();

                        //removemos el listener
                        productorComboModel.removeListDataListener( this );

                    }//end método intervalAdded

                    /**
                      * {@inheritDoc}
                     */
                    @Override
                    public void intervalRemoved( ListDataEvent e ) {
                        //ignore
                        
                    }//end método intervalRemoved

                    /**
                      * {@inheritDoc}
                      */
                    @Override
                    public void contentsChanged( ListDataEvent e ) {
                        //ignore
                        
                    }//end método contentsChanged

                } );

    }//end constructor

    /**
     * {@inheritDoc}
     */
    public EstablecimientoView( java.awt.Frame parent, boolean modal ) {
        this( parent, modal, (Establecimiento)null );
        
    }//end constructor
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        jPCentral = new javax.swing.JPanel();
        eLTFNombreEstablecimiento = new org.tri.swing.EditableLabelTF();
        jLDatosEstablecimiento = new javax.swing.JLabel();
        jLRenspa = new javax.swing.JLabel();
        eLFTFRenspa = new org.tri.swing.EditableLabelFTF();
        jLProductor = new javax.swing.JLabel();
        eLCBProductor = new org.tri.swing.EditableLabelCB();
        jLCuig = new javax.swing.JLabel();
        eLFTFCuig = new org.tri.swing.EditableLabelFTF();
        jLCV = new javax.swing.JLabel();
        eLFTFCV = new org.tri.swing.EditableLabelFTF();
        jLDireccionPostal = new javax.swing.JLabel();
        eLTFDireccionPostal = new org.tri.swing.EditableLabelTF();
        jLPartido = new javax.swing.JLabel();
        eLTFPartido = new org.tri.swing.EditableLabelTF();
        jLProvincia = new javax.swing.JLabel();
        eLTFProvincia = new org.tri.swing.EditableLabelTF();
        jLLote = new javax.swing.JLabel();
        eLTFLote = new org.tri.swing.EditableLabelTF();
        jLUltimaCaravana = new javax.swing.JLabel();
        eLFTFUltimaCaravana = new org.tri.swing.EditableLabelFTF();
        jLSuperficie = new javax.swing.JLabel();
        eLFTFSuperficie = new org.tri.swing.EditableLabelFTF();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(150, 0), new java.awt.Dimension(150, 0), new java.awt.Dimension(150, 32767));
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(150, 0), new java.awt.Dimension(150, 0), new java.awt.Dimension(150, 32767));
        jBAnimales = new javax.swing.JButton();
        jPBotones = new javax.swing.JPanel();
        jBGuardar = new javax.swing.JButton();
        jBResetear = new javax.swing.JButton();
        jBEliminar = new javax.swing.JButton();
        jLWaitIcon = new javax.swing.JLabel();
        jBCerrar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("Detalles");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
        });
        getContentPane().add(filler3, java.awt.BorderLayout.WEST);
        getContentPane().add(filler4, java.awt.BorderLayout.EAST);
        getContentPane().add(filler5, java.awt.BorderLayout.NORTH);
        getContentPane().add(filler6, java.awt.BorderLayout.SOUTH);

        jPCentral.setLayout(new java.awt.GridBagLayout());

        eLTFNombreEstablecimiento.setDefaultValue( "Nombre del Establecimiento" );
        eLTFNombreEstablecimiento.setFont(org.tri.gui.view.ViewConstants.defaultLabelFont.deriveFont( Font.BOLD, 24 ));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 20, 0);
        jPCentral.add(eLTFNombreEstablecimiento, gridBagConstraints);
        eLTFNombreEstablecimiento.makeEditable( );

        jLDatosEstablecimiento.setFont(org.tri.gui.view.ViewConstants.underlinedLabelFont);
        jLDatosEstablecimiento.setText("Datos del Establecimiento:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 10, 10);
        jPCentral.add(jLDatosEstablecimiento, gridBagConstraints);

        jLRenspa.setText("*Renspa:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
        jPCentral.add(jLRenspa, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 15);
        jPCentral.add(eLFTFRenspa, gridBagConstraints);
        try{
            eLFTFRenspa.makeEditable( new DefaultFormatterFactory(new javax.swing.text.MaskFormatter("##-###-#-#####-##")) );
        } catch(ParseException e){
            e.printStackTrace();
        }

        jLProductor.setText("*Productor:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
        jPCentral.add(jLProductor, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
        jPCentral.add(eLCBProductor, gridBagConstraints);
        eLCBProductor.makeEditable( productorComboModel );

        jLCuig.setText("*Cuig:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
        jPCentral.add(jLCuig, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 15);
        jPCentral.add(eLFTFCuig, gridBagConstraints);
        try {
            eLFTFCuig.makeEditable( new DefaultFormatterFactory(
                new javax.swing.text.MaskFormatter( "UU###" ) ) );

    } catch ( Exception ex ) {
        //ignore

    }

    jLCV.setText("CV:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 4;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLCV, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 5;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
    jPCentral.add(eLFTFCV, gridBagConstraints);
    eLFTFCV.makeEditable( new DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))) );

    jLDireccionPostal.setText("Dirección Postal:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 5;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLDireccionPostal, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 5;
    gridBagConstraints.gridwidth = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 15);
    jPCentral.add(eLTFDireccionPostal, gridBagConstraints);
    eLTFDireccionPostal.makeEditable( );

    jLPartido.setText("Partido:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 4;
    gridBagConstraints.gridy = 5;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLPartido, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 5;
    gridBagConstraints.gridy = 5;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
    jPCentral.add(eLTFPartido, gridBagConstraints);
    eLTFPartido.makeEditable( );

    jLProvincia.setText("Provincia:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 6;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLProvincia, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 6;
    gridBagConstraints.gridwidth = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 15);
    jPCentral.add(eLTFProvincia, gridBagConstraints);
    eLTFProvincia.makeEditable( );

    jLLote.setText("Lote:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 4;
    gridBagConstraints.gridy = 6;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLLote, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 5;
    gridBagConstraints.gridy = 6;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
    jPCentral.add(eLTFLote, gridBagConstraints);
    eLTFLote.makeEditable( );

    jLUltimaCaravana.setText("Última Caravana:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 7;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLUltimaCaravana, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 7;
    gridBagConstraints.gridwidth = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 15);
    jPCentral.add(eLFTFUltimaCaravana, gridBagConstraints);
    try {
        eLFTFUltimaCaravana.makeEditable( ( new DefaultFormatterFactory(
            new javax.swing.text.MaskFormatter( "UU###U###" ) ) ) );

} catch ( Exception ex ) {
    ex.printStackTrace();
    }

    jLSuperficie.setText("Superficie:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 4;
    gridBagConstraints.gridy = 7;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 10);
    jPCentral.add(jLSuperficie, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 5;
    gridBagConstraints.gridy = 7;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
    jPCentral.add(eLFTFSuperficie, gridBagConstraints);
    eLFTFSuperficie.makeEditable( new DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))) );
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 5;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    jPCentral.add(filler1, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.gridwidth = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
    jPCentral.add(filler2, gridBagConstraints);

    jBAnimales.setText("Ver Animales");
    jBAnimales.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jBAnimalesActionPerformed(evt);
        }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 8;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
    jPCentral.add(jBAnimales, gridBagConstraints);

    jPBotones.setLayout(new java.awt.GridBagLayout());

    jBGuardar.setText("Guardar");
    jBGuardar.setEnabled(false);
    jBGuardar.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jBGuardarActionPerformed(evt);
        }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
    jPBotones.add(jBGuardar, gridBagConstraints);

    jBResetear.setText("Resetear");
    jBResetear.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jBResetearActionPerformed(evt);
        }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
    jPBotones.add(jBResetear, gridBagConstraints);

    jBEliminar.setText("Eliminar");
    jBEliminar.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jBEliminarActionPerformed(evt);
        }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
    jPBotones.add(jBEliminar, gridBagConstraints);

    jLWaitIcon.setFocusable(false);
    jLWaitIcon.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
    jLWaitIcon.setIconTextGap(5);
    jLWaitIcon.setMinimumSize(new java.awt.Dimension(20, 20));
    jLWaitIcon.setPreferredSize(new java.awt.Dimension(20, 20));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    jPBotones.add(jLWaitIcon, gridBagConstraints);

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 8;
    gridBagConstraints.gridwidth = 5;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(15, 30, 0, 0);
    jPCentral.add(jPBotones, gridBagConstraints);

    jBCerrar.setText("Cerrar");
    jBCerrar.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jBCerrarActionPerformed(evt);
        }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 6;
    gridBagConstraints.gridy = 8;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
    gridBagConstraints.insets = new java.awt.Insets(15, 0, 0, 0);
    jPCentral.add(jBCerrar, gridBagConstraints);

    getContentPane().add(jPCentral, java.awt.BorderLayout.CENTER);

    pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jBCerrarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBCerrarActionPerformed
        cerrarDialog();
        
    }//GEN-LAST:event_jBCerrarActionPerformed

    private void jBEliminarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBEliminarActionPerformed
        //confirmamos antes de eliminar
        if ( JOptionPane.showConfirmDialog(
                this, String.format(
                "%s\n%s\n%s",
                "¿Esta seguro que desea eliminar el establecimiento?",
                "Esta acción eliminará todos los datos relacionados con el",
                "mismo, incluyendo compras y ventas realizadas." ),
                "Confirmación",
                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
             == JOptionPane.YES_OPTION ) {
            //realizamos las tareas de gui para indicar que se raliza una 
            //transacción
            fireWaitTriggers( true );
            jLWaitIcon.setText( "Eliminando..." );

            //solicitamos al frame que evictee las transacciones actuales si
            //las mismas estan ligadas al establecimiento
            MainFrame frame = ((MainFrame)getParent());
            
            if ( frame.getEstablecimiento() == establecimiento )
                frame.evictCurrentTransactions();
            
            //en un thread aparte eliminamos el productor y lo quitamos 
            //de la tabla
            EstablecimientoTransientWorker worker =
            new EstablecimientoTransientWorker( establecimiento );

            worker.addTransientListener( new EstablecimientoTransientHandler() );

            worker.execute();

        }//end if
        
    }//GEN-LAST:event_jBEliminarActionPerformed

    private void formWindowClosing( java.awt.event.WindowEvent evt ) {//GEN-FIRST:event_formWindowClosing
        cerrarDialog();
        
    }//GEN-LAST:event_formWindowClosing

    private void jBResetearActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBResetearActionPerformed
        eLTFNombreEstablecimiento.resetToDefault();
        eLFTFRenspa.resetToDefault();
        eLCBProductor.resetToDefault();
        eLFTFCuig.resetToDefault();
        eLFTFCV.resetToDefault();
        eLTFDireccionPostal.resetToDefault();
        eLTFPartido.resetToDefault();
        eLTFProvincia.resetToDefault();
        eLTFLote.resetToDefault();
        eLFTFUltimaCaravana.resetToDefault();
        eLFTFSuperficie.resetToDefault();
        
        jBGuardar.setEnabled( false );
        
    }//GEN-LAST:event_jBResetearActionPerformed

    private void jBGuardarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBGuardarActionPerformed
        //realizamos las tareas previas de GUI
        fireWaitTriggers( true );
        jLWaitIcon.setText( "Guardando..." );
        
        //desactivamos el editmode de todos los labels
        eLTFNombreEstablecimiento.deactivateEditMode();
        eLFTFRenspa.deactivateEditMode();
        eLCBProductor.deactivateEditMode();
        eLFTFCuig.deactivateEditMode();
        eLFTFCV.deactivateEditMode();
        eLTFDireccionPostal.deactivateEditMode();
        eLTFPartido.deactivateEditMode();
        eLTFProvincia.deactivateEditMode();
        eLTFLote.deactivateEditMode();
        eLFTFUltimaCaravana.deactivateEditMode();
        eLFTFSuperficie.deactivateEditMode();
        
        //seteamos las nuevas propiedades al establecimiento
        establecimiento.setNombre( eLTFNombreEstablecimiento.getText() );
        long renspa =  Establecimiento.renspaAsLong( (String)eLFTFRenspa.getValue() );
        String cuig =  (String)eLFTFCuig.getValue();
        
        if ( !eLFTFCV.getText().equals( "" ) )
            establecimiento.setCodigoVerificacion( 
                    ((Long)eLFTFCV.getValue()).intValue() );
        else
            establecimiento.setCodigoVerificacion( 0 );
        
        establecimiento.setDireccionPostal( eLTFDireccionPostal.getText() );
        establecimiento.setPartido( eLTFPartido.getText() );
        establecimiento.setProvincia( eLTFProvincia.getText() );
        establecimiento.setLote( eLTFLote.getText() );
        
        if ( !eLFTFUltimaCaravana.getText().trim().equals( "" ) )
            establecimiento.setUltimaCaravana( 
                    (String)eLFTFUltimaCaravana.getValue() );
        
        if ( !eLFTFSuperficie.getText().equals( "" ) ) 
            establecimiento.setSuperficie(
                    Math.abs( ((Long)eLFTFSuperficie.getValue()).intValue() ) );
        else
            establecimiento.setSuperficie( 0 );
        
        //en un thread aparte, guardamos el establecimiento
        Productor productor = productorComboModel.getElemento( 
                eLCBProductor.getSelectedIndex() );
        
        EstablecimientoPersistenceWorker worker =
                                         new EstablecimientoPersistenceWorker(
                establecimiento, productor, renspa, cuig);

        worker.addPersistenceListener(
                new EstablecimientoPersistenceHandler() );
        
        worker.execute();
        
    }//GEN-LAST:event_jBGuardarActionPerformed

    private void formWindowOpened( java.awt.event.WindowEvent evt ) {//GEN-FIRST:event_formWindowOpened
        if ( toDelete )
            jBEliminar.doClick();
        
    }//GEN-LAST:event_formWindowOpened

    private void jBAnimalesActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBAnimalesActionPerformed
        //armamos y mostramos la vista de animales
        new AnimalesListView( (MainFrame)this.getParent(), establecimiento ).
                setVisible( true );
        
    }//GEN-LAST:event_jBAnimalesActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private org.tri.swing.EditableLabelCB eLCBProductor;
    private org.tri.swing.EditableLabelFTF eLFTFCV;
    private org.tri.swing.EditableLabelFTF eLFTFCuig;
    private org.tri.swing.EditableLabelFTF eLFTFRenspa;
    private org.tri.swing.EditableLabelFTF eLFTFSuperficie;
    private org.tri.swing.EditableLabelFTF eLFTFUltimaCaravana;
    private org.tri.swing.EditableLabelTF eLTFDireccionPostal;
    private org.tri.swing.EditableLabelTF eLTFLote;
    private org.tri.swing.EditableLabelTF eLTFNombreEstablecimiento;
    private org.tri.swing.EditableLabelTF eLTFPartido;
    private org.tri.swing.EditableLabelTF eLTFProvincia;
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler2;
    private javax.swing.Box.Filler filler3;
    private javax.swing.Box.Filler filler4;
    private javax.swing.Box.Filler filler5;
    private javax.swing.Box.Filler filler6;
    private javax.swing.JButton jBAnimales;
    private javax.swing.JButton jBCerrar;
    private javax.swing.JButton jBEliminar;
    private javax.swing.JButton jBGuardar;
    private javax.swing.JButton jBResetear;
    private javax.swing.JLabel jLCV;
    private javax.swing.JLabel jLCuig;
    private javax.swing.JLabel jLDatosEstablecimiento;
    private javax.swing.JLabel jLDireccionPostal;
    private javax.swing.JLabel jLLote;
    private javax.swing.JLabel jLPartido;
    private javax.swing.JLabel jLProductor;
    private javax.swing.JLabel jLProvincia;
    private javax.swing.JLabel jLRenspa;
    private javax.swing.JLabel jLSuperficie;
    private javax.swing.JLabel jLUltimaCaravana;
    private javax.swing.JLabel jLWaitIcon;
    private javax.swing.JPanel jPBotones;
    private javax.swing.JPanel jPCentral;
    // End of variables declaration//GEN-END:variables

    /**
     * Asigna el establecimiento a la vista. Este método solo puede ser llamado
     * durante la construcción del objeto o para reasignar algunos valores
     * internamente, por eso es privado.
     * @param establecimiento establecimiento a asignar.
     */
    private void setEstablecimiento( Establecimiento establecimiento ) {
        if ( establecimiento == null ) {
            //si el establecimiento es nulo, generamos uno nuevo
            this.establecimiento = new Establecimiento();
            establecimientoNuevo = true;
            
            //desactivamos el boton eliminar ya que no esta en la base de datos
            jBEliminar.setEnabled( false );  
            
            //desactivamos el boton de ver animales (ya que no hay animales yet)
            jBAnimales.setEnabled( false );
            
        } else {
            //si el establecimiento existe, asignamos los valores a los campos
            //correspondientes de la vista
            this.establecimiento = establecimiento;
            
            eLTFNombreEstablecimiento.setDefaultValue( 
                    establecimiento.getNombre() );
            eLFTFRenspa.setDefaultValue( 
                    Establecimiento.renspaAsString( establecimiento.getRenspa() ) );
            eLCBProductor.setDefaultValue( 
                    establecimiento.getProductor().getRazonSocial() );
            defaultIndexProductor = eLCBProductor.getSelectedIndex();
            eLFTFCuig.setDefaultValue( establecimiento.getCuig() );
            eLFTFCV.setDefaultValue( establecimiento.getCodigoVerificacion() > 0 
                                     ? String.valueOf(
                                     establecimiento.getCodigoVerificacion() ) 
                                     : "" );
            eLTFDireccionPostal.setDefaultValue( 
                    establecimiento.getDireccionPostal() );
            eLTFPartido.setDefaultValue( establecimiento.getPartido() );
            eLTFProvincia.setDefaultValue( establecimiento.getProvincia() );
            eLTFLote.setDefaultValue( establecimiento.getLote() );
            eLFTFUltimaCaravana.setDefaultValue( 
                    establecimiento.getUltimaCaravana() );
            eLFTFSuperficie.setDefaultValue( establecimiento.getSuperficie() > 0 
                                             ? String.valueOf( 
                                             establecimiento.getSuperficie() ) 
                                             : "");
            
            if ( establecimiento.getUltimaCaravana() == null )
                this.changeUltimaCaravanaFormat();
            
        }
        
    }//end método setEstablecimiento
    
    /**
     * Cambia el formato de la última caravana en función del cuig.
     */
    private void changeUltimaCaravanaFormat() {
        //obtenemos el valor viejo
        String oldValue = (String)eLFTFUltimaCaravana.getValue();

        try {           
            this.eLFTFUltimaCaravana.makeEditable( new DefaultFormatterFactory(
                    new javax.swing.text.MaskFormatter( String.format( "%sU###",
                                             ( (String)eLFTFCuig.getValue()).
                    replace( "A", "'A" ).replace( "H","'H" ).replace( "L","'L" ).
                    replace( "U","'U" ) ) ) ) );
                    

        } catch ( Exception ex ) {
            ex.printStackTrace();

        }

        //intentamos asignar el valor viejo
        if ( oldValue != null ) {
            oldValue = (String)eLFTFCuig.getValue() + oldValue.substring( 5 );

            this.eLFTFUltimaCaravana.setText( oldValue );

        }

    }//end método changeUltimaCaravanaFormat
    
    /**
     * Devuelve el establecimiento representado por esta vista.
     * @return establecimiento de la vista.
     */
    public Establecimiento getEstablecimiento() {
        return establecimiento;
                
    }//end método getEstablecimiento
    
    /**
     * Devuelve el resultado de la operación de esta vista, utilizando alguna
     * de las constantes de {@code ViewConstants}.
     * @return valor que indica el resultado de esta vista.
     */
    public int getResult() {
        return result;
        
    }//end método getResult
    
    /**
     * Muestra la vista especificamente para eliminar el establecimiento.
     */
    public void showToDelete() {
        toDelete = true;
        
        setVisible( true );
                
    }//end método showToDelete
    
    /**
     * Método auxiliar utilizado para cerrar la vista.
     */
    private void cerrarDialog() {
        //si no hay cambios válidos o el usuario no uqiere guardar los cambios,
        //cerramos el dialog
        if ( !jBGuardar.isEnabled() || askUndoChanges() ) 
            this.dispose();

    }//end método cerrarDialog
    
    /**
     * Método auxiliar que se encarga de preguntar al usuario si deshea deshacer
     * los cambios realizados sobre la vista.
     * @return <li>true si el usuario responde que si.<li>false si el usuario
     * responde que no.
     */
    private boolean askUndoChanges() {
        int option = JOptionPane.showConfirmDialog( 
                this,
                "Se realizaron cambios sobre el "
                + "establecimiento,\nesta seguro que desea salir?",
                "¿Desea deshacer los cambios?",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.INFORMATION_MESSAGE );

        return option == JOptionPane.YES_OPTION;

    }//end método askUndoChanges
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void propertyChange( PropertyChangeEvent evt ) {
        //comprobamos que los campos obligatorios esten completos
        boolean readyToSave = eLTFNombreEstablecimiento.getText().length() > 0
                              && eLFTFRenspa.getText().length() > 0
                              && eLFTFCuig.getValue() != null
                              && ((String)eLFTFCuig.getValue()).length() > 0
                              && eLCBProductor.getText().length() > 0;
        
        //si el valor modificado fué regresado a su valor por defecto, hay
        //que comprobar si todavía existe razón para guardar el objeto o
        //volvio a su estado inicial
        if ( !(Boolean)evt.getNewValue() ) 
            readyToSave = readyToSave && 
                          (  eLTFNombreEstablecimiento.isModified() 
                          || eLFTFRenspa.isModified() 
                          || eLFTFCuig.isModified()
                          || eLCBProductor.isModified() 
                          || eLFTFCV.isModified()
                          || eLTFDireccionPostal.isModified()
                          || eLTFPartido.isModified()
                          || eLTFProvincia.isModified()
                          || eLTFLote.isModified()
                          || eLFTFUltimaCaravana.isModified()
                          || eLFTFSuperficie.isModified() );
        
        //a partir de la criteria anterior, activamos o no el boton de guardar
        jBGuardar.setEnabled( readyToSave );
        
        //si se seteo la ultima caravana alteramos el cuig para que corresponda.
        if ( evt.getSource() == this.eLFTFUltimaCaravana && 
             this.eLFTFUltimaCaravana.getValue() != null &&
             this.eLFTFUltimaCaravana.isModified() ) {
            
            this.eLFTFCuig.setText( 
                    ((String)eLFTFUltimaCaravana.getValue()).substring( 0, 5 ) );
            
            //también seteamos el formato de la última caravana para que sea
            //consistente
            SwingUtilities.invokeLater( new Runnable() {

                @Override
                public void run() {
                    EstablecimientoView.this.changeUltimaCaravanaFormat();
                    
                }
                
            });
            
        }
        
        //si se seteo el cuig, tenemos que asegurarnos de que la ultima caravana
        //le corresponda
        if ( evt.getSource() == this.eLFTFCuig
             && this.eLFTFCuig.getValue() != null
             && this.eLFTFCuig.isModified() )       
            this.changeUltimaCaravanaFormat();                     
                                            
    }//end método propertyChange

    /**
     * {@inheritDoc}
     */
    @Override
    public void doneFillingCombo() {        
        //si el establecimiento asignado ya tiene productor, lo seleccionamos 
        //como default del campo productor
        if ( establecimiento.getProductor() != null ) {
            eLCBProductor.setDefaultValue( 
                    establecimiento.getProductor().getRazonSocial() );
            defaultIndexProductor = eLCBProductor.getSelectedIndex();
            
        }//end if
        
    }//end método doneFillingcombo

    /**
     * {@inheritDoc}
     */
    @Override
    public void errorFillingCombo( ExecutionException ex ) {
        dispose();
        ((MainFrame)getParent()).recoverFromFail();
        
    }//end método errorFillingCombo         
        
    /**
     * Método auxiliar que lanza algunos triggers gráficos para indicar al 
     * usuario que se esta realizando una tarea en background y que va a 
     * tener que esperar. Mientras los triggers estan activados, no se 
     * puede interactuar con la gui.
     * @param inicio bandera indicando si iniciar o finalizar los triggers.
     */
    private void fireWaitTriggers( boolean inicio ) {
        if ( inicio ) {
            jPCentral.requestFocus();
            waitIndicator = new WaitIndicator( jPCentral );
        } else 
            waitIndicator.dispose();
        
        jBGuardar.setEnabled( inicio ? !inicio : inicio );
        
        jLWaitIcon.setEnabled( true );
        jLWaitIcon.setIcon( inicio ? loadingIcon : null );
        jLWaitIcon.setText( "" );

    }//end método fireWaitTriggers
    
    /**
     * Listener que realiza algunas tareas una vez completada la tarea de 
     * eliminar un establecimiento.
     */
    class EstablecimientoTransientHandler implements TransientListener {

        /** Bandera que indica si ocurrio un error o no. */
        private boolean error;

        /**
         * {@inheritDoc}
         */
        @Override
        public void doneTransit() {
            //reactivamos la interfaz
            fireWaitTriggers( false );

            //si no ocurrio ningun error, asignamos el resultado y cerramos
            //la vista
            if ( !error ) {
                result = ViewConstants.DELETED;

                cerrarDialog();

            }//end if

        }//end método doneTransit

        /**
         * {@inheritDoc}
         */
        @Override
        public void errorTransit( ExecutionException ex ) {
            error = true;

            dispose();
            ((MainFrame)getParent()).recoverFromFail();
            
        }//end método errorTransit
        
        
    }//end clase EstablecimientoTransientHandler
    
    /**
     * Listener que se encarga de realizar algunas tareas luego de que se
     * persiste el establecimiento.
     */
    class EstablecimientoPersistenceHandler implements PersistenceListener {

        /** Bandera que indica si ocurrio algun error durante la persistencia. */
        private boolean error;

        /**
         * {@inheritDoc}
         */
        @Override
        public void donePersisting() {
            //rehabilitamos la gui
            fireWaitTriggers( false );

            //si no ocurrio ningún error...
            if ( !error ) {
                if ( establecimientoNuevo ) {
                    //y el establecimiento es nuevo, asignamos el resultado
                    //y cerramos la vista
                    result = ViewConstants.ADDED;

                    cerrarDialog();

                } else {
                    //y es un productor modificado, asignamos el resultado
                    //pero no cerramos la vista, simplemente la actualizamos
                    result = ViewConstants.MODIFIED;

                    setEstablecimiento( establecimiento );
                    
                    jLWaitIcon.setText( "Guardado." );

                    SwingUtils.futureClearLabel( jLWaitIcon );

                }                

            } else {
                //"reiniciamos" el establecimiento ya que no se pudo guardar
                
                //productor previo del establecimiento (si lo tuviera)                                
                Productor prodOriginal = 
                productorComboModel.getElemento( defaultIndexProductor );
                //productor asignado acutalmente
                Productor prodAsignado = establecimiento.getProductor();
                
                //solo reiniciamos la mayoria de los campos si el 
                //establecimiento no es nuevo
                if ( !establecimientoNuevo ) {
                    establecimiento.setNombre(
                            eLTFNombreEstablecimiento.getDefaultValue() );
                    establecimiento.setCuig( eLFTFCuig.getDefaultValue() );
                    establecimiento.setDireccionPostal(
                            eLTFDireccionPostal.getDefaultValue() );
                    establecimiento.setPartido( eLTFPartido.getDefaultValue() );
                    establecimiento.setProvincia( eLTFProvincia.getDefaultValue() );
                    establecimiento.setUltimaCaravana(
                            eLFTFUltimaCaravana.getDefaultValue() );
                    
                    try {
                        establecimiento.setRenspa( Long.parseLong(
                                eLFTFRenspa.getDefaultValue() ) );

                    } catch ( NumberFormatException ex ) {
                        establecimiento.setRenspa( 0 );

                    }

                    try {
                        establecimiento.setCodigoVerificacion(
                                Integer.parseInt( eLFTFCV.getDefaultValue() ) );

                    } catch ( NumberFormatException ex ) {
                        establecimiento.setCodigoVerificacion( 0 );

                    }

                    try {
                        establecimiento.setSuperficie( Integer.parseInt(
                                eLFTFSuperficie.getDefaultValue() ) );

                    } catch ( NumberFormatException ex ) {
                        establecimiento.setSuperficie( 0 );

                    }
                
                    //si el productor cambio
                    if ( !prodOriginal.equals( prodAsignado ) ) {
                        //si ya estaba asignado a un productor
                        if ( prodAsignado != null )
                            //quitamos el establecimiento del productor anterior
                            prodAsignado.quitarEstablecimiento( establecimiento );

                        //asignamos el productor original
                        prodOriginal.agregarEstablecimiento( establecimiento );

                    }//end if
                    
                } else { //si el establecimiento es nuevo
                    //y se le asigno un productor, lo quitamos
                    if ( prodAsignado != null )
                        prodAsignado.quitarEstablecimiento( establecimiento );
                
                    //deshabilitamos el botón de eliminar ya que no
                    jBEliminar.setEnabled( false );
                
                }

            }

        }//end método donePersisting

        /**
         * {@inheritDoc}
         */
        @Override
        public void errorPersisting( ExecutionException ex ) {
            error = true;

            if ( ex.getCause() instanceof EstablecimientoDuplicadoException ) 
                JOptionPane.showMessageDialog( EstablecimientoView.this,
                                               ex.getCause().getMessage(), 
                                               "Establecimiento Duplicado", 
                                               JOptionPane.INFORMATION_MESSAGE);
            else {
                dispose();
                ((MainFrame)getParent()).recoverFromFail();
                
            }

        }//end método errorPersisting           

    }//end clase EstablecimientoPersistenceHandler

}//end clase EstablecimientoView
